﻿// ScreenClock.cpp : 定义应用程序的入口点。
//
#define _CRT_SECURE_NO_WARNINGS

#include "framework.h"
#include "ScreenClock.h"
#include "Resource.h"
#include "config.hpp"

#define MAX_LOADSTRING 100

// 全局变量:
HINSTANCE hInst;                                // 当前实例
WCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名
double dpi;
HWND hText,g_hWnd;

// 此代码模块中包含的函数的前向声明:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
VOID CALLBACK TimerProc(UINT, UINT, UINT, UINT);
BOOL CALLBACK SettingsProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK VisibProc(HWND, UINT, WPARAM, LPARAM);
int TestRunning();

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    
    TestRunning();

    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: 在此处放置代码。

    // 初始化全局字符串
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_SCREENCLOCK, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // 执行应用程序初始化:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SCREENCLOCK));

    MSG msg;

    // 主消息循环:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SCREENCLOCK));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)CreateSolidBrush(0);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_SCREENCLOCK);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // 将实例句柄存储在全局变量中

   HWND hWnd = CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_LAYERED, szWindowClass, szTitle, WS_POPUP,
       (GetSystemMetrics(SM_CXSCREEN) - 240) / 2, 0, 240, 36, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}



LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HMENU hPop;
    static RECT rc;
    static HFONT hf;
    static HBRUSH hBlack;

    static BOOL moving,lock;

    static ScreenClock::Config cfg("config.txt");

    switch (message)
    {
    case WM_CTLCOLORSTATIC:
    {
        SetBkMode((HDC)wParam, 1);
        SetTextColor((HDC)wParam, RGB(200, 90, 90));
        return (LRESULT)hBlack;
    }
    case WM_CREATE:
    {
        g_hWnd = hWnd;
        dpi = 1.0;
        //ScreenClock::Config cfg("config.txt");
        if (DpiAware(&dpi) != 0)MessageBox(nullptr, L"DPI感知失败。", szTitle, MB_ICONINFORMATION);
        SetLayeredWindowAttributes(hWnd, 0, 255, LWA_ALPHA);
        hPop = CreatePopupMenu();
        AppendMenu(hPop, MF_STRING, 2001, L"调整可见度...(&A)");
        AppendMenu(hPop, MF_STRING, 2004, L"锁定窗口(&L)");
        AppendMenu(hPop, MF_STRING, 2002, L"设置...(&S)");
        AppendMenu(hPop, MF_SEPARATOR, 0, 0);
        AppendMenu(hPop, MF_STRING, 2003, L"退出(&X)\tAlt+F4");

        //创建静态的字体和黑刷子
        hf = SimpleFont(L"微软雅黑",33*dpi,false);
        hBlack = CreateSolidBrush(0);
        
        //调整窗口大小
        

        GetWindowRect(hWnd, &rc);

        hText = CreateWindow(L"static", L"星期日  00:00:00", WS_VISIBLE | WS_CHILD | SS_CENTER, 0, 0,
            0, 0, hWnd, (HMENU)1001, hInst, NULL);
        SendMessage(hText, WM_SETFONT, (WPARAM)hf, MAKELPARAM(true, true));

        SendMessage(hWnd, WM_AUTOSIZE, 0, 0);

        // 创建计时器开始
        SetTimer(hWnd, 0, 10, (TIMERPROC)TimerProc);

        break;
    }
    case WM_AUTOSIZE:{
        GetWindowRect(hWnd, &rc);
        HDC hdc = GetDC(hWnd);
        SelectObject(hdc, hf);
        SIZE sz;
        GetTextExtentPoint32(hdc, L"  星期一  00:00:00  ", lstrlenW(L"  星期一  00:00:00  "), &sz);
        ReleaseDC(hWnd, hdc);
        rc.left = 0;
        rc.right = sz.cx;
        rc.top = 0;
        rc.bottom = 36 * dpi;
        rc.left = (GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2;
        MoveWindow(hWnd, rc.left, 0, rc.right, rc.bottom, true);
        GetWindowRect(hWnd, &rc);
        MoveWindow(hText, 0, 0, rc.right-rc.left, rc.bottom-rc.top, true);
        
        break;
    }

    case WM_LBUTTONDOWN:
    {
        break;
    }
    case WM_LBUTTONUP: {
        break;
    }
    case WM_MOUSEMOVE: {
        if (lock == true)break;

        static POINT startPt;
        static POINT mousePtOri;
        static RECT rcWindowOri;
        if (wParam == 1) {
            if (moving == false) {
                moving = true;
                GetCursorPos(&mousePtOri);
                GetWindowRect(hWnd, &rcWindowOri);
            }
            SetCursor(LoadCursor(nullptr, IDC_SIZEALL));
            POINT mousePt;
            POINT moving;
            GetCursorPos(&mousePt);
            moving.x = mousePt.x - mousePtOri.x;
            moving.y = mousePt.y - mousePtOri.y;
            SetWindowPos(hWnd, NULL, rcWindowOri.left + moving.x, rcWindowOri.top + moving.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
        }
        else {
            moving = false;
        }
        break;
    }
    case WM_MOVE:{
        RECT rcw;
        GetWindowRect(hWnd, &rcw);
        int defX = (GetSystemMetrics(SM_CXSCREEN) - (rcw.right - rcw.left)) / 2;
        if (rcw.left < 0) {
            SetWindowPos(hWnd, NULL, 0, rcw.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
        }
        if (rcw.right > GetSystemMetrics(SM_CXSCREEN)){
            SetWindowPos(hWnd, NULL, GetSystemMetrics(SM_CXSCREEN)-(rcw.right-rcw.left), rcw.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
        }
        if (rcw.top < 0) {
            SetWindowPos(hWnd, NULL, rcw.left, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
        }
        if (rcw.bottom > GetSystemMetrics(SM_CYSCREEN)) {
            SetWindowPos(hWnd, NULL,rcw.left, GetSystemMetrics(SM_CYSCREEN) - (rcw.bottom - rcw.top), 0, 0, SWP_NOSIZE | SWP_NOZORDER);
        }
        if (rcw.left >= defX - 20 && rcw.left <= defX + 20 && rcw.top < 0) {
            SetWindowPos(hWnd, NULL, defX, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
        }
        break;
    }

    case WM_RBUTTONDOWN: {
        POINT pt;
        GetCursorPos(&pt);
        TrackPopupMenu(hPop, TPM_RIGHTBUTTON, pt.x, pt.y, 0, hWnd, NULL);
        break;
    }
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 分析菜单选择:
            switch (wmId)
            {
            case 2001: {
                DialogBox(hInst, MAKEINTRESOURCE(IDD_VISIB), hWnd, (DLGPROC)VisibProc);
                break;
            }
            case 2002: {
                DialogBox(hInst, MAKEINTRESOURCE(IDD_SETTINGS), hWnd, (DLGPROC)SettingsProc);
                break;
            }
            case 2003: {
                DestroyWindow(hWnd);
                break;
            }
            case 2004: {
                lock = !lock;
                if (lock) {
                    CheckMenuItem(hPop, 2004, MF_BYCOMMAND | MF_CHECKED);
                }
                else {
                    CheckMenuItem(hPop, 2004, MF_BYCOMMAND | MF_UNCHECKED);
                }
                break;
            }
            }
        }
        break;
    case WM_RELOAD: {

        break;
    }
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: 在此处添加使用 hdc 的任何绘图代码...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        KillTimer(hWnd, 1);
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

VOID CALLBACK TimerProc(UINT x0, UINT x1, UINT x2, UINT x3) {
    WCHAR bfr[100];
    const WCHAR* days[7] = { L"星期日",L"星期一",L"星期二",L"星期三",L"星期四", L"星期五",L"星期六" };
    static time_t ttmLast;
    time_t ttm = time(nullptr);
    if (ttm != ttmLast) {
        tm stm = *localtime(&ttm);
        wsprintf(bfr, L"%ls  %02d:%02d:%02d", days[stm.tm_wday], stm.tm_hour, stm.tm_min, stm.tm_sec);
        SetWindowText(hText, bfr);
        ttmLast = ttm;
    }
}

BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    static HWND hcbFont, hBack, hFore，hLock,hRemember,hLeftButton;
    switch (message) {
    case WM_INITDIALOG: {
        hcbFont = GetDlgItem(hDlg, IDC_COMBO1);
        hLeftButton = GetDlgItem(hDlg, IDC_COMBO2);
        PopulateFontComboBox(hcbFont);
        for (int i = 0; i <= 4; i++) {
            ComboBox_AddString(hLeftButton, ScreenClock::leftButtonCaption[i]);
        }

        break;
    }
    case WM_COMMAND: {
        switch (LOWORD(wParam)) {
        case IDOK:
        {
            
        }
        case IDCANCEL: {
            EndDialog(hDlg, 0);
            return true;
        }
        }
        break;
    }
    }
    return false;
}

BOOL CALLBACK VisibProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    static HWND hSlide;
    switch (message) {
    case WM_INITDIALOG: {
        hSlide = GetDlgItem(hDlg, IDC_SLIDER1);
        SendMessage(hSlide, TBM_SETRANGE, true, MAKELPARAM(20, 100));
        SendMessage(hSlide, TBM_SETPOS, true, 100);
        SendMessage(hDlg, WM_HSCROLL, 0, (LPARAM)hSlide);
        break;
    }
    case WM_HSCROLL: {
        if (lParam == (LPARAM)hSlide) {
        int num = SendMessage((HWND)lParam, TBM_GETPOS, 0, 0);
        wchar_t tmp[15];
        wsprintf(tmp, L"%d%%", num);
        SetWindowText(GetDlgItem(hDlg, IDC_STATIC), tmp);
        SetLayeredWindowAttributes(g_hWnd, 0, 255 * num / 100, LWA_ALPHA);
        }
        break;
    }
    case WM_COMMAND: {
        switch (LOWORD(wParam)) {
        
        case IDOK:
        {

        }
        case IDCANCEL: {
            EndDialog(hDlg, 0);
            return true;
        }
        }
        break;
    }
    }
    return false;
}

int TestRunning() {
    // ============================
    // 阻止程序多开的代码（放在 WinMain 最前面）
    // ============================
    HANDLE hMutex = CreateMutex(
        NULL,              // 默认安全属性
        TRUE,              // 初始时拥有互斥体（即锁定）
        L"MyUniqueAppMutex" // 唯一的互斥体名称，自己定义，确保全局唯一！
    );

    if (hMutex == NULL)
    {
        // 创建互斥体失败，可能是权限等问题，可以根据需要处理
        MessageBox(NULL, L"无法创建互斥体，程序可能无法正常运行。", L"错误", MB_ICONERROR);
        return 1;
    }

    if (GetLastError() == ERROR_ALREADY_EXISTS)
    {
        // 已经有一个实例在运行了
        CloseHandle(hMutex); // 释放句柄（虽然程序即将退出）
        MessageBox(NULL, L"程序已经在运行中！", L"提示", MB_ICONINFORMATION | MB_OK);
        exit(0); // 直接退出，不启动新实例
    }
}